
<script setup lang="ts">
import {computed, nextTick, ref, watch} from "vue";
import { createSelector3Service } from "./selector3Service.ts";
import type {ApiParams, ExternalField, OptionField} from "./type.ts";
import {Select} from "ant-design-vue";
import type {DefaultOptionType, SelectValue} from "ant-design-vue/es/select";

const ASelect = Select;
const ASelectOption = Select.Option;

interface Props {
  modalName?: string;
  apiPath?: string;
  apiParams?: ApiParams;
  masterValue?: any;
  isDisabled?: boolean;
  optionField?: OptionField;
  externalField?: ExternalField;
  externalData?: any;
}

const props = withDefaults(defineProps<Props>(), {
  apiPath: '/business/dtoRoleCase',
  apiParams: () => ({
    searchKey: 'name',
    masterKey: 'roleName',
  }),
  modalName: '业务',
  masterValue: undefined,
  isDisabled: true,
  optionField: () => ({
    key: 'id',
    value: 'name',
  }),
  externalField: () => ({
    key: 'id',
    value: 'name',
  }),
  externalData: () => ({}),
});

// 创建服务实例
const selectorService = createSelector3Service({
  apiPath: props.apiPath,
  apiParams: props.apiParams,
  modalName: props.modalName,
  optionField: props.optionField
});

const {
  fetching: selectorFetching,
  selectorInfo,
  selectedValues,
  onSearch,
  onFocus,
  onBlur,
  onChange,
} = selectorService;

const placeTxt = computed(() => `请选择${props.modalName}`);

const isUpdatingFromExternal = ref(false);
const isUpdatingFromInternal = ref(false);

// 监听外部数据变化，同步到选择器
watch(
    () => props.externalData,
    (newExternalData) => {
      if (isUpdatingFromInternal.value) return;
      if (newExternalData && Array.isArray(newExternalData)) {
        isUpdatingFromExternal.value = true;
        // 多选模式下，externalData 应该是一个数组
        selectorInfo.value.option = newExternalData;
        selectedValues.value = newExternalData.map(item => item[props.externalField.value]);

        nextTick(() => {
          isUpdatingFromExternal.value = false;
        });
      }
    },
    { deep: true, immediate: true }
);

// 监听选择器变化，同步到外部数据
watch(
    () => selectedValues.value,
    (newSelectedValues) => {
      if (isUpdatingFromExternal.value) return;
      if (props.externalData && Array.isArray(props.externalData)) {
        isUpdatingFromInternal.value = true;
        // 清空外部数据数组
        props.externalData.length = 0;

        // 根据选中的值重新填充外部数据
        newSelectedValues?.forEach(value => {
          const foundItem = selectorInfo.value.option.find(option =>
              option[props.optionField.value] === value
          );

          if (foundItem) {
            props.externalData.push({
              [props.externalField.key]: foundItem[props.optionField.key],
              [props.externalField.value]: foundItem[props.optionField.value],
            });
          } else {
            // 如果是新创建的项目
            props.externalData.push({
              [props.externalField.key]: undefined,
              [props.externalField.value]: value
            });
          }
        });

        nextTick(() => {
          isUpdatingFromInternal.value = false;
        });
      }
    },
    { deep: true }
);

// 处理搜索
const handleSearch = (searchValue: string) => {
  if(!props.isDisabled){
    onSearch(searchValue, props.masterValue);
  }
};

// 处理聚焦
const handleFocus = () => {
  onFocus(props.masterValue);
};

const handleChange = (values: SelectValue, _option: DefaultOptionType | DefaultOptionType[]) => {
  onChange(values as string[]);
};

defineExpose({
  selectorInfo,
  selectedValues,
});
</script>

<template>
  <a-select
      v-model:value="selectedValues"
      mode="multiple"
      :placeholder="placeTxt"
      :filter-option="false"
      :not-found-content="selectorFetching ? undefined : null"
      @focus="handleFocus"
      @blur="onBlur"
      @change="handleChange"
      popupClassName="custom-dropdown"
      :disabled="props.isDisabled || !props.masterValue"
      class="tool-select-multiple"
      show-search
      @search="handleSearch"
  >
    <a-select-option
        v-for="s in selectorInfo.option"
        :key="s[props.optionField.key]"
        :value="s[props.optionField.value]"
    >
      {{ s[props.optionField.value] }}
    </a-select-option>
  </a-select>
</template>

<style scoped>
.tool-select-multiple {
  width: 100%;
  display: flex;
  height: 100%;
}
.tool-select-multiple>::v-deep(.ant-select-selector){
  width: 100%;
}
</style>